
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;


public class Testing {

	private static List<Process> prcAuctionClients = new ArrayList<Process>();  
	private static List<BufferedWriter> writerAuctionClients = new ArrayList<BufferedWriter>();
	private static List<BufferedReader> readerAuctionClients = new ArrayList<BufferedReader>();
	private static BufferedReader readerManagementClient; 

	static int clientsCount = 6;
	static int auctionsPerMin = 30;
	static int auctionDuration = 10;
	static int updateIntervalSec = 5;
	static int bidsPerMin = 30;
	
	static int numberOfBids = 0;
	
	private static Timer timerAuctionPerMin;
	private static Timer timerUpdateIntervalSec;
	private static Timer timerBidsPerMin;
	
	static Date startDate; 
	
	@SuppressWarnings("deprecation")
	public static void main(String[] args) throws IOException, InterruptedException {
		java.io.InputStream is = ClassLoader.getSystemResourceAsStream("loadtest.properties");
		if (is != null) 
		{
			java.util.Properties props = new java.util.Properties();
			try 
			{
				props.load(is);
				clientsCount = Integer.valueOf(props.getProperty("clients"));
				auctionsPerMin = Integer.valueOf(props.getProperty("auctionsPerMin"));
				auctionDuration = Integer.valueOf(props.getProperty("auctionDuration"));
				updateIntervalSec = Integer.valueOf(props.getProperty("updateIntervalSec"));
				bidsPerMin = Integer.valueOf(props.getProperty("bidsPerMin"));
				
				is.close();
			}
			catch (Exception e) {
				System.out.println(e.getMessage());
			}
		}
		else 
		{
			System.out.println("Properties file not found!");
		}	
		
		startDate = new Date();

		String path = (new File(".")).getCanonicalPath() + "/bin";
		
		ProcessBuilder pbAnalyticsServer = new ProcessBuilder("java", "analyticsServer.AnalyticsServer", "AnalyticsServer");
		pbAnalyticsServer.directory(new File(path));
		Process prcAnalyticsServer = pbAnalyticsServer.start();
        BufferedReader brAnalyticsServer = new BufferedReader(new InputStreamReader(prcAnalyticsServer.getInputStream()));
       	System.out.println(brAnalyticsServer.readLine());
		
		ProcessBuilder pbBillingServer = new ProcessBuilder("java", "billingServer.BillingServer", "BillingServer");
		pbBillingServer.directory(new File(path));
		Process prcBillingServer = pbBillingServer.start();
        BufferedReader brBillingServer = new BufferedReader(new InputStreamReader(prcBillingServer.getInputStream()));
       	System.out.println(brBillingServer.readLine());

        ProcessBuilder pbAuctionServer = new ProcessBuilder("java", "auctionServer.ServerUI", "12430", "AnalyticsServer", "BillingServer");
		pbAuctionServer.directory(new File(path));
		Process prcAuctionServer = pbAuctionServer.start();
		BufferedReader brAuctionServer = new BufferedReader(new InputStreamReader(prcAuctionServer.getInputStream()));
		System.out.println(brAuctionServer.readLine());

        for (int  i = 0; i < clientsCount; i++)
		{
	        ProcessBuilder pbAuctionClient = new ProcessBuilder("java", "auctionClient.Client", "127.0.0.1", "12430", String.valueOf(12431 + i));
			pbAuctionClient.directory(new File(path));
			Process prcAuctionClient = pbAuctionClient.start();
			BufferedWriter writerAuctionClient = new BufferedWriter(new OutputStreamWriter(prcAuctionClient.getOutputStream ()));
			BufferedReader readerAuctionClient = new BufferedReader (new InputStreamReader(prcAuctionClient.getInputStream ()));
			System.out.println(readerAuctionClient.readLine());
			writerAuctionClient.write("!login user" + String.valueOf(i) + "\n");
			writerAuctionClient.flush();
			System.out.println(readerAuctionClient.readLine());

			prcAuctionClients.add(prcAuctionClient);
			writerAuctionClients.add(writerAuctionClient);
			readerAuctionClients.add(readerAuctionClient);
		}
		
		//auctionPerMin
		timerAuctionPerMin = new Timer();
		timerAuctionPerMin.schedule( new TimerTask() {
		    public void run() {
		    	for (int  i = 0; i < clientsCount; i++)
				{
	    			try {
			    		for (int  j = 0; j < auctionsPerMin; j++)
						{
			    			writerAuctionClients.get(i).write("!create " + String.valueOf(auctionDuration) + " product" + String.valueOf((i+1) * 10000000 + j) + "\n");
							writerAuctionClients.get(i).flush();
							numberOfBids++;
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
		    }
		 }, 0, 60*1000);

		//updateIntervalSec
		timerUpdateIntervalSec = new Timer();
		timerUpdateIntervalSec.schedule( new TimerTask() {
		    public void run() {
		    	for (int  i = 0; i < clientsCount; i++)
				{
	    			try {
	    				writerAuctionClients.get(i).write("!list" + "\n");
	    				writerAuctionClients.get(i).flush();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
		    }
		 }, 0, updateIntervalSec*1000);
		
		//auctionPerMin
		timerBidsPerMin = new Timer();
		timerBidsPerMin.schedule( new TimerTask() {
		    public void run() {
		    	for (int  i = 0; i < clientsCount; i++)
				{
	    			try {
			    		for (int  j = 0; j < auctionsPerMin; j++)
						{
			    			int auctionID = (int)(Math.random() * (numberOfBids + 1));
			    			long diffInMillis = (new Date()).getTime() - startDate.getTime();
			    			long auctionPrice = diffInMillis;  
			    			writerAuctionClients.get(i).write("!bid " + String.valueOf(auctionID) + " " + String.valueOf(auctionPrice) + "\n");
							writerAuctionClients.get(i).flush();
						}
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
		    }
		 }, 0, 60*1000);
		
		ProcessBuilder pbManagementClient = new ProcessBuilder("java", "managementClient.ManagementClient", "AnalyticsServer", "BillingServer");
		pbManagementClient.directory(new File(path));
		Process prcManagementClient = pbManagementClient.start();
		BufferedWriter writerManagementClient = new BufferedWriter(new OutputStreamWriter(prcManagementClient.getOutputStream ()));
		readerManagementClient = new BufferedReader(new InputStreamReader(prcManagementClient.getInputStream()));
		System.out.println(readerManagementClient.readLine());
		writerManagementClient.write("!subscribe (USER_.*)|(BID_.*) \n");
		writerManagementClient.flush();
		System.out.println(readerManagementClient.readLine());
		writerManagementClient.write("!auto \n");
		writerManagementClient.flush();
		writerManagementClient.close();
		System.out.println(readerManagementClient.readLine());

		Thread threadMonitoring = new Thread() {
			public void run() 
			{
				try
				{
					if (readerManagementClient.ready())
					{
						System.out.println(readerManagementClient.readLine());
					}
					for (int  i = 0; i < readerAuctionClients.size(); i++)
					{
						if (readerAuctionClients.get(i).ready())
							System.out.println(readerAuctionClients.get(i).readLine());
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		};
		threadMonitoring.start();
			
		while((new Date()).getTime() - startDate.getTime() < 300*1000)
		{
			
        }
	        
		System.out.println("Finishing");
		threadMonitoring.stop();
		timerAuctionPerMin.cancel();
		timerBidsPerMin.cancel();
		timerUpdateIntervalSec.cancel();
		for (int  i = 0; i < prcAuctionClients.size(); i++)
	        prcAuctionClients.get(i).destroy();
		
		prcAnalyticsServer.destroy();
        prcBillingServer.destroy();
        prcManagementClient.destroy();
		prcAuctionServer.destroy();
	}

}

